/*
 * Copyright (c) 1990, 2022, shwfed and/or its affiliates. All rights reserved.
 *
 * @date: 2022-08-24
 *
 */
package cn.junglead.common.utils;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * 密码学DES双向对称加密工具
 *
 * @author Gary.Wang
 * @version 1.0
 */
public class CipherDesUtil extends CipherBase {
    private final static String ALGORITHMS = "DES/ECB/PKCS5Padding";
    private final static Logger logger = LoggerFactory.getLogger(CipherAesUtil.class);

    /**
     * ECB 模式的 DES 加密核心方法
     * @param key 加密密钥，字符长度为8位
     * @param plaintext 明文原文
     * @return 返回密文结果
     */
    public static byte[] encrypt(String key, String plaintext){
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHMS);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(), "DES"));
            return cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException |
                 BadPaddingException e) {
            logger.error("DES 加密发生异常，异常原因：{}", e.getMessage());
        }
        return new byte[0];
    }

    /**
     * 自定义模式的 DES 加密核心方法
     * @param algorithms 算法模式
     * @param key 加密密钥，16位长度
     * @param plaintext 明文内容
     * @return 返回加密后的密文
     */
    public static byte[] encrypt(String algorithms, String key, String plaintext){
        try {
            Cipher cipher = Cipher.getInstance(algorithms);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(), "DES"));
            return cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException |
                 BadPaddingException e) {
            logger.error("DES 加密发生异常，异常原因：{}", e.getMessage());
        }
        return new byte[0];
    }

    /**
     * 标准模式的 DES 加密简单方法
     * @param outputFormat 返回格式，CipherDesUtil 类的静态属性
     * @param key 加密密钥，字符长度为8位
     * @param plaintext 明文原文
     * @return 返回加密后的结果
     */
    public static String encrypt(int outputFormat, String key, String plaintext){
        byte[] byteContent = encrypt(key, plaintext);
        if (outputFormat == FORMAT_HEX) {
            return Hex.encodeHexString(byteContent);
        }
        return Base64.getEncoder().encodeToString(byteContent);
    }

    /**
     * 自定义模式的 DES 加密简单方法
     * @param algorithms 加密模式
     * @param outputFormat 输出格式
     * @param key 密钥，可以是16位长度
     * @param plaintext 明文内容
     * @return 返回加密后的结果
     */
    public static String encrypt(String algorithms, int outputFormat, String key, String plaintext){
        byte[] byteContent = encrypt(algorithms, key, plaintext);
        if (outputFormat == FORMAT_HEX) {
            return Hex.encodeHexString(byteContent);
        }
        return Base64.getEncoder().encodeToString(byteContent);
    }


    /**
     * ECB 模式的 DES 解密核心方法
     * @param key 解密密钥，字符长度为8位
     * @param input 待解密的密文
     * @return 返回解密后的原文
     */
    public static byte[] decrypt(String key, byte[] input){
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHMS);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes(), "DES"));
            return cipher.doFinal(input);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            logger.error("DES 解密发生异常，异常原因：{}", e.getMessage());
        }
        return new byte[0];
    }

    /**
     * 自定义模式的 DES 加密核心方法
     *
     * @param algorithms 算法模式
     * @param key 解密密钥，16位长度
     * @param input 待解密的密文
     * @return 返回解密后的原文数组
     */
    public static byte[] decrypt(String algorithms, String key, byte[] input){
        try {
            Cipher cipher = Cipher.getInstance(algorithms);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes(), "DES"));
            return cipher.doFinal(input);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            logger.error("DES 解密发生异常，异常原因：{}", e.getMessage());
        }
        return new byte[0];
    }



    /**
     * 常用的 DES 解密方法
     * @param inputFormat 输入格式， 为 CipherAesUtil 类的静态属性
     * @param key 解密密钥，字符长度为8位
     * @param ciphertext 密文
     * @return 返回解密后的结果
     */
    public static String decrypt(int inputFormat, String key, String ciphertext){
        byte[] input;
        if (inputFormat == FORMAT_HEX) {
            try {
                input = Hex.decodeHex(ciphertext.toCharArray());
            } catch (DecoderException e) {
                input = new byte[0];
                logger.error("DES 解密前的二进制转码发生异常，异常原因：{}", e.getMessage());
            }
        } else {
            input = Base64.getDecoder().decode(ciphertext);
        }
        if (input != null && input.length > 0){
            byte[] byteContent = decrypt(key, input);
            return new String(byteContent, StandardCharsets.UTF_8);
        }
        return null;
    }

    /**
     * 通用的自定义模式的DES解密方法
     * @param algorithms 指定算法
     * @param inputFormat 输入格式
     * @param key 密钥，可以为16位长度
     * @param ciphertext 密文
     * @return 返回解密后的结果
     */
    public static String decrypt(String algorithms, int inputFormat, String key, String ciphertext){
        byte[] input;
        if (inputFormat == FORMAT_HEX) {
            try {
                input = Hex.decodeHex(ciphertext.toCharArray());
            } catch (DecoderException e) {
                input = new byte[0];
                logger.error("DES 解密前的二进制转码发生异常，异常原因：{}", e.getMessage());
            }
        } else {
            input = Base64.getDecoder().decode(ciphertext);
        }
        if (input != null && input.length > 0){
            byte[] byteContent = decrypt(algorithms, key, input);
            return new String(byteContent, StandardCharsets.UTF_8);
        }
        return null;
    }
}
